package com.xzit.rental.security;

import com.xzit.rental.entity.Permission;
import com.xzit.rental.entity.User;
import com.xzit.rental.service.IPermissionService;
import com.xzit.rental.service.IUserService;
import jakarta.annotation.Resource;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Objects;

/*它实现了Spring Security框架中的UserDetailsService接口。其主要职责是根据提供的用户名从数据库加载对应的用户信息以及相关的权限信息，
    并将这些信息整合封装到UserDetails对象（在这里实际返回的是自定义的User对象，它应该符合UserDetails规范要求）中返回，
    供Spring Security进行认证和授权相关的操作使用。*/
@Component
public class CustomerUserDetailsService implements UserDetailsService {

    @Resource
    private IUserService userService;

    @Resource
    private IPermissionService permissionService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库中按照username查询user对象
        User user = userService.selectByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在！");
        }
        // 查询用户权限列表，并将这些权限信息设置到user对象中
        List<Permission> permissions = permissionService.selectPermissionListByUserId(user.getId());
        user.setPermissionList(permissions);

        // 利用 Java 8 的 Stream API 对权限列表进行处理，先过滤掉为null的权限对象，接着提取每个权限对象中的权限代码
        // 再次过滤掉可能为null的权限代码字符串，最后将处理后的权限代码字符串列表转换为数组。
        List<String> list = permissions.stream().filter(Objects::nonNull)
                .map(Permission::getPermissionCode)
                .filter(Objects::nonNull)
                .toList();
        String[] array = list.toArray((new String[list.size()]));
        // 将权限代码字符串数组转换为List<GrantedAuthority>
        List<GrantedAuthority> authorityList = AuthorityUtils.createAuthorityList(array);
        // 并将其设置到user对象的Authorities属性中（通过user.setAuthorities方法），这样返回的user对象就包含了完整的用户基本信息以及权限信息
        user.setAuthorities(authorityList);

        return user;
    }

}
